package gnss

import (
	"dgo/goutils/dnet"
	"dgo/goutils/utils"
	"fmt"
	"io"
	"net"
	"sync/atomic"
	"time"
)

var (
	__ntripconn_handle_counter uint32 = 0
)

type NtripSimpleCasterConn struct {
	sendingflag       int32
	sendTaskStartFlag int32
	reqDisFlag        int32

	ReqHead       *NtripHead
	RemoteAddr    string
	ConnectedTime time.Time
	conn          net.Conn
	connType      uint8
	caster        *NtripSimpleCaster
	handle        uint32
	sessionid     string

	recv_cacheBuf []byte

	disReason string

	TagPtr interface{}
}

func newSimpleCasterConn(_conn net.Conn, caster *NtripSimpleCaster) *NtripSimpleCasterConn {
	rval := &NtripSimpleCasterConn{
		handle:            atomic.AddUint32(&__ntripconn_handle_counter, 1),
		conn:              _conn,
		caster:            caster,
		sendTaskStartFlag: 0,
		connType:          TYPE_UNKOWN,
		reqDisFlag:        0,
		ReqHead:           NewNtripHead(),
		recv_cacheBuf:     make([]byte, 128),
	}
	rval.ConnectedTime = time.Now()
	rval.RemoteAddr = _conn.RemoteAddr().String()
	rval.sessionid = fmt.Sprintf("%.5d%s", rval.handle, utils.RandKeyString(12))
	return rval
}

func (this *NtripSimpleCasterConn) onClose() {
	caster := this.caster
	if caster == nil {
		return
	}
	if this.connType == TYPE_NTRIPSERVER {
		caster.handleNtripSvrClose(this)
	} else if this.connType == TYPE_NTRIPCLIENT {
		caster.handleNtripCltClose(this)
	}
	this.caster = nil
	this.recv_cacheBuf = nil
	this.ReqHead = nil
	this.conn = nil
}

func (this *NtripSimpleCasterConn) GetSessionID() string {
	return this.sessionid
}

func (this *NtripSimpleCasterConn) GetLastDisReason() string {
	return this.disReason
}

func (this *NtripSimpleCasterConn) ExtractUserAgent() string {
	return utils.DelNonChineseCharEx(this.ReqHead.ExtractUserAgent(), ' ')
}

func (this *NtripSimpleCasterConn) ExtractFromAddr() string {
	return this.ReqHead.GetClientIP(this.RemoteAddr)
}

func (this *NtripSimpleCasterConn) ExtractXForwaredForEx() string {
	return this.ReqHead.ExtractXForwaredForEx(this.RemoteAddr)
}

func (this *NtripSimpleCasterConn) Write(buf []byte) (n int, err error) {
	conn := this.conn
	if conn == nil {
		return 0, io.ErrClosedPipe
	}
	n, err = conn.Write(buf)
	if err != nil {
		this.RequestDis(fmt.Sprintf("发送数据异常:%s", err.Error()))
	}
	return
}

func (this *NtripSimpleCasterConn) RequestDis(reason string) {
	if atomic.CompareAndSwapInt32(&this.reqDisFlag, 0, 1) {
		this.disReason = reason
		conn := this.conn
		if conn != nil {
			conn.Close()
		}
	}
}

func (this *NtripSimpleCasterConn) onNtripCltAccept() {
	this.caster.handleNtripCltAccept(this)
}

func (this *NtripSimpleCasterConn) onNtripCltRecv(buf []byte) {
	this.caster.handleNtripCltRecvBuf(this, buf)
}

func (this *NtripSimpleCasterConn) onNtripSvrAccept() {
	this.caster.handleNtripSvrAccept(this)
}

func (this *NtripSimpleCasterConn) onNtripSvrRecv(buf []byte) {
	this.caster.handleNtripSvrRecvBuf(this, buf)
}

func (this *NtripSimpleCasterConn) HandleRecv() {
	if utils.GoFunCatchException {
		defer utils.PanicHandler()
	}
	dnet.SetKeepAlive(this.conn, false)
	defer this.onClose()
	rp := NewNtripHeadDecoder()

	for {
		buf := this.recv_cacheBuf

		n, err := this.conn.Read(buf)
		if err != nil {
			str := fmt.Sprintf("处理(%s)接收数据请求时出现了异常:%s ", this.RemoteAddr, err.Error())
			this.RequestDis(str)
			break
		}

		if this.connType == TYPE_NTRIPSERVER {
			this.onNtripSvrRecv(buf[:n])
		} else if this.connType == TYPE_NTRIPCLIENT {
			this.onNtripCltRecv(buf[:n])
		} else {
			if this.innerDecodePrerequest(rp, buf[:n]) {
				rp.Cleanup()
				rp = nil
			}
		}
	}
}

/*
*

	返回true:表示解码完成
*/
func (this *NtripSimpleCasterConn) innerDecodePrerequest(rp *NtripHeadDecoder, buf []byte) bool {
	l := len(buf)
	for i := 0; i < l; i++ {
		r := rp.InputByte(buf[i])
		if r == 1 {

			if !this.ReqHead.ParseText(rp.String()) {
				this.RequestDis(fmt.Sprintf("非法的Ntrip连接接入:%s", utils.BufToHexStr(rp.Bytes(), 0, "")))
				return true
			}
			this.connType = this.ReqHead.GetRequestType()
			if this.connType == TYPE_NTRIPCLIENT {
				this.onNtripCltAccept()
				if this.reqDisFlag == 0 && i+1 < l {
					this.onNtripCltRecv(buf[i+1:])
				}
				return true
			}

			if this.connType == TYPE_NTRIPSERVER {
				this.onNtripSvrAccept()
				if this.reqDisFlag == 0 && i+1 < l {
					this.onNtripSvrRecv(buf[i+1:])
				}
				this.recv_cacheBuf = make([]byte, 1024)
				return true
			}
			this.RequestDis(fmt.Sprintf("未知的Ntrip连接接入:%s", utils.BufToHexStr(rp.Bytes(), 0, "")))
			return true
		} else if rp.Len() > int(this.caster.max_head_size) {
			this.RequestDis(fmt.Sprintf("非法的Ntrip连接接入, 解码异常. 数据:%s", utils.BufToHexStr(rp.Bytes(), 0, "")))
			return true
		}
	}
	return false
}
